import { z } from "zod";
import { writeFile } from "fs/promises";
import { join } from "path";
import { CodeIndexOrchestrator } from "../services/orchestrator.js";

export const getIndexStatusSchema = z.object({
  verbose: z.boolean().optional().default(false)
});

export type GetIndexStatusArgs = z.infer<typeof getIndexStatusSchema>;

export async function getIndexStatusTool(
  args: GetIndexStatusArgs,
  orchestrator: CodeIndexOrchestrator
): Promise<string> {
  try {
    const status = orchestrator.getStatus();
    const verbose = args.verbose || false;
    
    // Check if there are actually indexed documents by checking cache
    let actuallyIndexed = false;
    let indexedFileCount = 0;
    let cachedFiles: string[] = [];
    let totalBlocks = 0;
    try {
      // Check if cache manager has any cached files (indicates indexing has occurred)
      const cacheManager = (orchestrator as any).cacheManager;
      await cacheManager.loadCache(); // Load cache from disk first
      const allHashes = cacheManager.getAllHashes();
      cachedFiles = Object.keys(allHashes);
      if (cachedFiles.length > 0) {
        actuallyIndexed = true;
        indexedFileCount = cachedFiles.length;
        
        // If verbose, calculate total blocks from cached data
        if (verbose) {
          try {
            // Access the vector store to get more detailed stats
            const vectorStore = (orchestrator as any).vectorStore;
            // Note: This is a rough estimation - in production you might want to store block counts in cache
            totalBlocks = status.stats?.totalBlocks || 0;
          } catch (error) {
            // Fallback to stats if available
            totalBlocks = status.stats?.totalBlocks || 0;
          }
        }
      }
    } catch (error) {
      // Cache check failed, use orchestrator status
    }
    
    let response = `📊 **Code Index Status**\n\n`;
    
    // Determine actual status based on vector store content
    const actualState = actuallyIndexed ? 'indexed' : status.state;
    
    // Status badge
    const statusEmoji = {
      'standby': '⏸️',
      'indexing': '⚡',
      'indexed': '✅',
      'error': '❌'
    };
    
    response += `**State:** ${statusEmoji[actualState]} ${actualState.toUpperCase()}\n`;
    
    if (actuallyIndexed) {
      response += `**Message:** Index contains ${indexedFileCount} files\n\n`;
    } else {
      response += `**Message:** ${status.message}\n\n`;
    }
    
    // Show stats if available
    if (status.stats) {
      response += `**Indexing Statistics:**\n`;
      response += `- Files processed: ${status.stats.processed}\n`;
      response += `- Files skipped: ${status.stats.skipped}\n`;
      response += `- Code blocks indexed: ${status.stats.totalBlocks}\n`;
      response += `- Errors encountered: ${status.stats.errors}\n\n`;
    }
    
    // Show last indexed time
    if (status.lastIndexed) {
      const lastIndexedDate = new Date(status.lastIndexed);
      response += `**Last Indexed:** ${lastIndexedDate.toLocaleString()}\n\n`;
    }
    
    // Add verbose information if requested
    if (verbose && actuallyIndexed && cachedFiles.length > 0) {
      response += `📋 **Detailed Index Information**\n\n`;
      
      // Show file type breakdown
      const fileExtensions = new Map<string, number>();
      const fileSizes = new Map<string, number>();
      
      cachedFiles.forEach(filePath => {
        const ext = filePath.split('.').pop()?.toLowerCase() || 'no-ext';
        fileExtensions.set(ext, (fileExtensions.get(ext) || 0) + 1);
      });
      
      // Sort extensions by count
      const sortedExtensions = Array.from(fileExtensions.entries())
        .sort((a, b) => b[1] - a[1])
        .slice(0, 10); // Show top 10 file types
      
      response += `**File Types Indexed:**\n`;
      sortedExtensions.forEach(([ext, count]) => {
        const percentage = ((count / cachedFiles.length) * 100).toFixed(1);
        response += `- .${ext}: ${count} files (${percentage}%)\n`;
      });
      response += '\n';
      
      // Show directory breakdown (top level only)
      const directories = new Map<string, number>();
      cachedFiles.forEach(filePath => {
        // Get the first directory component
        const parts = filePath.replace(/^\.\//, '').split('/');
        const topDir = parts.length > 1 ? parts[0] : 'root';
        directories.set(topDir, (directories.get(topDir) || 0) + 1);
      });
      
      const sortedDirs = Array.from(directories.entries())
        .sort((a, b) => b[1] - a[1])
        .slice(0, 10); // Show top 10 directories
      
      response += `**Directory Distribution:**\n`;
      sortedDirs.forEach(([dir, count]) => {
        const percentage = ((count / cachedFiles.length) * 100).toFixed(1);
        response += `- ${dir}/: ${count} files (${percentage}%)\n`;
      });
      response += '\n';
      
      // Write full file list to log file when verbose
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const logFileName = `codebase-rag-status-${timestamp}.log`;
      // Use the configuration directory (where the command was run) instead of process.cwd()
      const configDir = (orchestrator as any).configDirectory || process.cwd();
      const logFilePath = join(configDir, logFileName);
      
      try {
        const logContent = [
          `# Codebase RAG Status Report`,
          `Generated: ${new Date().toISOString()}`,
          `Total Files: ${cachedFiles.length}`,
          ``,
          `## File Types Distribution`,
          ...sortedExtensions.map(([ext, count]) => {
            const percentage = ((count / cachedFiles.length) * 100).toFixed(1);
            return `- .${ext}: ${count} files (${percentage}%)`;
          }),
          ``,
          `## Directory Distribution`,
          ...sortedDirs.map(([dir, count]) => {
            const percentage = ((count / cachedFiles.length) * 100).toFixed(1);
            return `- ${dir}/: ${count} files (${percentage}%)`;
          }),
          ``,
          `## Complete File List`,
          ...cachedFiles.map((file, index) => `${index + 1}. ${file}`)
        ].join('\n');
        
        await writeFile(logFilePath, logContent, 'utf8');
        
        response += `**File List Log:**\n`;
        response += `- Complete file list written to: ${logFileName}\n`;
        response += `- Total files logged: ${cachedFiles.length}\n\n`;
        
        response += `**Recently Indexed Files (showing last 5):**\n`;
        const recentFiles = cachedFiles.slice(-5).reverse();
        recentFiles.forEach((file) => {
          response += `- ${file}\n`;
        });
        response += '\n';
        
      } catch (error) {
        response += `**Recently Indexed Files:**\n`;
        const recentFiles = cachedFiles.slice(-10).reverse();
        recentFiles.forEach((file, index) => {
          if (index < 5) { // Show only first 5 to avoid too much output
            response += `- ${file}\n`;
          }
        });
        if (cachedFiles.length > 5) {
          response += `... and ${cachedFiles.length - 5} more files\n`;
        }
        response += `\n⚠️ Could not write log file: ${error instanceof Error ? error.message : String(error)}\n\n`;
      }
    }
    
    // Add status-specific guidance
    switch (actualState) {
      case 'standby':
        response += `**Next Steps:**\n`;
        response += `- Use the \`index_codebase\` tool to start indexing a directory\n`;
        response += `- Make sure your embedding service and vector database are configured\n`;
        break;
        
      case 'indexing':
        response += `**Currently Processing:**\n`;
        response += `- Indexing is in progress, please wait for completion\n`;
        response += `- You can monitor progress through status updates\n`;
        break;
        
      case 'indexed':
        response += `**Ready for Search:**\n`;
        response += `- Use the \`search_code\` tool to find relevant code\n`;
        response += `- Use \`clear_index\` to reset if needed\n`;
        break;
        
      case 'error':
        response += `**Action Required:**\n`;
        response += `- Check the error message above\n`;
        response += `- Verify your configuration and try indexing again\n`;
        response += `- Use \`clear_index\` to reset if needed\n`;
        break;
    }
    
    return response;
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);
    return `❌ Failed to get index status: ${errorMessage}`;
  }
}
